我们已经讨论了在编译或链接包含模板的程序时出现的bug。在成功构建之后，最具挑战性的任务是确保程序在运行时的行为正确。因为模板所表示的泛型代码行为只依赖于该模板的外部使用(当然比普通的类和函数要多得多)，所以模板有时会使这项任务变得困难。跟踪程序是一种软件工具，可以通过在开发早期检测模板定义中的问题来减轻这方面的工作。

跟踪程序是一个用户定义的类，可以用作要测试的模板的参数。跟踪程序也是一个原型，其只是为了满足模板的需求。跟踪程序应该生成对其调用操作的跟踪，可以通过实验验证算法的效率，以及操作的顺序。

下面是一个可以用来测试排序算法跟踪器的例子:

\begin{tcolorbox}[colback=webgreen!5!white,colframe=webgreen!75!black]
\hspace*{0.75cm}C++17前，必须在翻译单元中在类声明之外初始化静态成员。
\end{tcolorbox}

\hspace*{\fill} \\ %插入空行
\noindent
\textit{debugging/tracer.hpp}
\begin{lstlisting}[style=styleCXX]
#include <iostream>
class SortTracer {
	private:
	int value; // integer value to be sorted
	int generation; // generation of this tracer
	inline static long n_created = 0; // number of constructor calls
	inline static long n_destroyed = 0; // number of destructor calls
	inline static long n_assigned = 0; // number of assignments
	inline static long n_compared = 0; // number of comparisons
	inline static long n_max_live = 0; // maximum of existing objects
	
	// recompute maximum of existing objects
	static void update_max_live() {
		if (n_created-n_destroyed > n_max_live) {
			n_max_live = n_created-n_destroyed;
		}
	}

	public:
	static long creations() {
		return n_created;
	}
	static long destructions() {
		return n_destroyed;
	}
	static long assignments() {
		return n_assigned;
	}
	static long comparisons() {
		return n_compared;
	}
	static long max_live() {
		return n_max_live;
	}

	public:
	// constructor
	SortTracer (int v = 0) : value(v), generation(1) {
		++n_created;
		update_max_live();
		std::cerr << "SortTracer #" << n_created
				<< ", created generation " << generation
				<< " (total: " << n_created - n_destroyed
				<< ")\n";
	}

	// copy constructor
	SortTracer (SortTracer const& b)
	: value(b.value), generation(b.generation+1) {
		++n_created;
		update_max_live();
		std::cerr << "SortTracer #" << n_created
				<< ", copied as generation " << generation
				<< " (total: " << n_created - n_destroyed
				<< ")\n";
	}

	// destructor
	~SortTracer() {
		++n_destroyed;
		update_max_live();
		std::cerr << "SortTracer generation " << generation
				<< " destroyed (total: "
				<< n_created - n_destroyed << ")\n";
	}

	// assignment
	SortTracer& operator= (SortTracer const& b) {
		++n_assigned;
		std::cerr << "SortTracer assignment #" << n_assigned
				<< " (generation " << generation
				<< " = " << b.generation
				<< ")\n";
		value = b.value;
		return *this;
	}

	// comparison
	friend bool operator < (SortTracer const& a,
							SortTracer const& b) {
		++n_compared;
		std::cerr << "SortTracer comparison #" << n_compared
				<< " (generation " << a.generation
				<< " < " << b.generation
				<< ")\n";
		return a.value < b.value;
	}

	int val() const {
		return value;
	}
};
\end{lstlisting}

除了用于排序的值，跟踪器还提供了几个成员来跟踪实际的排序:对于每个对象，生成跟踪的依据是从原始对象中删除了多少个复制操作。也就是说，原始操作generation == 1，操作的直接副本为generation == 2，副本的副本为generation == 3，依此类推。其他静态成员会跟踪创建(构造函数调用)、销毁、赋值比较和最大值操作。

这个特殊的跟踪器允许跟踪实体创建和销毁的模式，以及给定模板执行的赋值和比较。下面的测试程序演示了C++标准库的std::sort()算法:

\hspace*{\fill} \\ %插入空行
\noindent
\textit{debugging/tracertest.cpp}
\begin{lstlisting}[style=styleCXX]
#include <iostream>
#include <algorithm>
#include "tracer.hpp"

int main()
{
	// prepare sample input:
	SortTracer input[] = { 7, 3, 5, 6, 4, 2, 0, 1, 9, 8 };
	
	// print initial values:
	for (int i=0; i<10; ++i) {
		std::cerr << input[i].val() << ’ ’;
	}
	std::cerr << ’\n’;
	
	// remember initial conditions:
	long created_at_start = SortTracer::creations();
	long max_live_at_start = SortTracer::max_live();
	long assigned_at_start = SortTracer::assignments();
	long compared_at_start = SortTracer::comparisons();
	
	// execute algorithm:
	std::cerr << "---[ Start std::sort() ]--------------------\n";
	std::sort<>(&input[0], &input[9]+1);
	std::cerr << "---[ End std::sort() ]----------------------\n";
	
	// verify result:
	for (int i=0; i<10; ++i) {
		std::cerr << input[i].val() << ’ ’;
	}
	std::cerr << "\n\n";
	
	// final report:
	std::cerr << "std::sort() of 10 SortTracer’s"
			<< " was performed by:\n "
			<< SortTracer::creations() - created_at_start
			<< " temporary tracers\n "
			<< "up to "
			<< SortTracer::max_live()
			<< " tracers at the same time ("
			<< max_live_at_start << " before)\n "
			<< SortTracer::assignments() - assigned_at_start
			<< " assignments\n "
			<< SortTracer::comparisons() - compared_at_start
			<< " comparisons\n\n";
}
\end{lstlisting}

运行这个程序会产生相当多的输出，但是可以从最终输出中得出很多结论。对于std::sort()函数的实现，有如下输出:

\begin{tcblisting}{commandshell={}}
std::sort() of 10 SortTracer’s was performed by:
 9 temporary tracers
 up to 11 tracers at the same time (10 before)
 33 assignments
 27 comparisons
\end{tcblisting}

例如，尽管在排序时在程序中创建了9个临时跟踪器，但最多有两个跟踪器存在。

因此，跟踪器扮演了两个角色:证明标准sort()算法不需要跟踪器的更多功能(不需要操作符==和>)，并且让我们了解算法的成本，这并不能说明排序模板的正确性。




































